/**
 * controller基类
 * by wyy
 */
namespace MVC {
    export class Manager extends Singleton {
        private _controller = {};
        private _view = {};
        private _model = {};

        get Controller() {
            return Controller;
        }
        get View() {
            return View;
        }
        get Model() {
            return Model;
        }

        registController($key, $controller, $view?, $model?) {
            this._controller[$key] = $controller;
            $controller.init();
            if ($view) {
                $controller.view = $view;
                this.registView($key, $view);
            };
            if ($model) {
                $controller.model = $model;
                this.registModel($key, $model);
            }
        }
        getController($key): Controller {
            return this._controller[$key];
        }
        registView($key, $view) {
            this._view[$key] = $view;
            $view.controller = Frame.MVC.getController($key);
        }
        getView($key): View {
            return this._view[$key];
        }
        registModel($key, $model) {
            this._model[$key] = $model;
            $model.controller = Frame.MVC.getController($key);
        }
        getModel($key): Model {
            return this._model[$key];
        }
    }

    class Controller {
        view: View;
        model;

        constructor($view = null, $model = null) {
            this.view = $view;
            this.model = $model;
        }
        //控制器初始化
        init() { }
        //界面初始化
        viewInit() { }
        //界面打开
        viewOpen(...param) { }
        viewClose() { }
        /**
         * 加载资源并打开视图
         * @param $layer 
         * @param $resGrpName 
         * @param param 
         */
        loadResAndOpenView($layer, $resGrpName, ...param) {
            Frame.RES.loadGroup($resGrpName,
                () => { this.openView($layer, ...param); }, () => { }, this);
        }
        openView($layer, ...param) {
            //view打开完成后回调
            Frame.Message.addListener(`${this.view.hashCode}_open_complete`, () => {
                this.viewOpen(...param);
                //监听器使用完毕删除 避免重复创建
                Frame.Message.removeListenerByType(`${this.view.hashCode}_open_complete`);
            }, this);
            if (!this.view.isShow) {
                $layer.addChild(this.view);
                this.view.isShow = true;
            }

        }
        closeView() {
            this.view.removeFromParent();
        }
    }

    class Model {
        protected _controller: Controller;

        constructor($controller?) {
            this._controller = $controller;
        }
    }

    export class View extends eui.Component implements eui.UIComponent {
        protected _controller: Controller;
        protected _isInit: boolean = false;
        isShow: boolean = false;
        key;
        constructor($skinName?) {
            super();
            $skinName && (this.skinName = $skinName);

            //监听
            this.addEventListener(egret.Event.ADDED_TO_STAGE, this.addedToStage, this);
            this.addEventListener(egret.Event.REMOVED_FROM_STAGE, this.removeFromStage, this);

        }
        protected addedToStage() {
            if (!this._isInit) {
                this.init();
                this._controller && this._controller.viewInit();
                this._isInit = true;
            }
            this.open();
            //view打开完成后回调
            Frame.Message.dispatch(`${this.hashCode}_open_complete`);
        }

        protected removeFromStage() {
            this.isShow = false;
            this._controller && this._controller.viewClose();
        }
        set controller($controller) {
            this._controller = $controller;
        }
        removeFromParent() {
            if (this.parent) {
                this.parent.removeChild(this);
                this.isShow = false;
            }
        }
        changeParentGrp(targetGrp: egret.DisplayObjectContainer) {
            let stagePoint = this.parent.localToGlobal(this.x, this.y);
            let targetGrpPoint = targetGrp.globalToLocal(stagePoint.x, stagePoint.y);
            this.parent.removeChild(this);
            this.x = targetGrpPoint.x;
            this.y = targetGrpPoint.y;
            targetGrp.addChild(this);
        }
        protected init() { }
        protected open() { }
    }

}


